package com.innovation.ic.sc.base.service.sc.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.innovation.ic.b1b.framework.util.DateUtils;
import com.innovation.ic.sc.base.mapper.sc.ActionMessageMapper;
import com.innovation.ic.sc.base.model.sc.ActionMessage;
import com.innovation.ic.sc.base.model.sc.ActionMessageUserLink;
import com.innovation.ic.sc.base.model.sc.User;
import com.innovation.ic.sc.base.pojo.constant.handler.RedisStorage;
import com.innovation.ic.sc.base.pojo.enums.RedisKeyPrefixEnum;
import com.innovation.ic.sc.base.pojo.variable.ActionMessagePojo;
import com.innovation.ic.sc.base.pojo.variable.ServiceResult;
import com.innovation.ic.sc.base.service.ServiceHelper;
import com.innovation.ic.sc.base.service.sc.ActionMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @ClassName ActionMessageServiceImpl
 * @Description 动作消息实现类
 * @Date 2022/10/8
 * @Author myq
 */
@Slf4j
@Service
public class ActionMessageServiceImpl extends ServiceImpl<ActionMessageMapper, ActionMessage> implements ActionMessageService {

    @Resource
    private ServiceHelper serviceHelper;

    /**
     * @Description: 分页列表
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2023/1/615:54
     */
    @Override
    public ServiceResult<PageInfo<ActionMessagePojo>> page(int pageNo, int pageSize, String id) {
        PageHelper.startPage(pageNo, pageSize);

        List<ActionMessagePojo> actionMessageList = this.baseMapper.pageInfo(id);
        return ServiceResult.ok(new PageInfo<>(actionMessageList), "动作消息分页数据OK");
    }

    /**
     * 分页列表，从redis中取数据
     *
     * @param pageNo
     * @param pageSize
     * @param id
     * @return
     */
    @Override
    public ServiceResult<PageInfo<ActionMessagePojo>> pageRedis(int pageNo, int pageSize, String id) {
        PageHelper.startPage(pageNo, pageSize);

//        Set<String> stringSet1 = serviceHelper.getRedisManager().zReverseRangeByScore("api:v1:actionMessage:page_USR06524", Long.MIN_VALUE, Long.MAX_VALUE);
//        Set<String> stringSet2 = serviceHelper.getRedisManager().zReverseRangeByScore("api:v1:actionMessage:page_USR06524", (pageNo - 1) * pageSize, pageSize);
//        Set<String> stringSet3 = serviceHelper.getRedisManager().zRange("api:v1:actionMessage:page_USR06524", (pageNo - 1) * pageSize, pageSize);
//        Set<String> stringSet4 = serviceHelper.getRedisManager().zReverseRange("api:v1:actionMessage:page_USR06524", (pageNo - 1) * pageSize, pageSize);
//        Set<String> stringSet5 = serviceHelper.getRedisManager().zRangeByScore("api:v1:actionMessage:page_USR06524", Long.MIN_VALUE, Long.MAX_VALUE);
//        Set<ZSetOperations.TypedTuple<String>> stringSet6 = serviceHelper.getRedisManager().zRangeByScoreWithScores("api:v1:actionMessage:page_USR06524", (pageNo - 1) * pageSize, pageSize);
//        Set<ZSetOperations.TypedTuple<String>> stringSet7 = serviceHelper.getRedisManager().zReverseRangeWithScores("api:v1:actionMessage:page_USR06524", (pageNo - 1) * pageSize, pageSize);
//        Set<String> stringSet = serviceHelper.getRedisManager().zReverseRangeByScore("api:v1:actionMessage:page_USR06524", Long.MIN_VALUE, Long.MAX_VALUE, (pageNo - 1) * pageSize, pageSize);

        String key = RedisKeyPrefixEnum.ACTION_MESSAGE_PAGE.getCode() + "_" + id;
        Set<String> stringSet = serviceHelper.getRedisManager().zReverseRangeByScore(key, Long.MIN_VALUE, Long.MAX_VALUE, (pageNo - 1) * pageSize, pageSize);

        if (null != stringSet) {
            if (stringSet.size() == 1) {
                String str = stringSet.iterator().next();
                if (RedisStorage.EMPTY_VALUE.equals(str)) {
                    // 这个用户没有消息（redis里没有，mysql里也没有）
                    return ServiceResult.ok(null, "动作消息分页数据OK");
                } else {
                    // 这个用户有一条消息
                    List<ActionMessagePojo> actionMessagePojoList = serviceHelper.getModelHandler().stringSetToActionMessagePojoList(stringSet);
                    return ServiceResult.ok(new PageInfo<>(actionMessagePojoList), "动作消息分页数据OK");
                }
            } else if (stringSet.size() == 0) {
                // redis里没有消息，然后需要查数据库
                ServiceResult<PageInfo<ActionMessagePojo>> serviceResult = this.page(pageNo, pageSize, id);
                if (null != serviceResult && null != serviceResult.getResult() && null != serviceResult.getResult().getList() && serviceResult.getResult().getList().size() > 0) {
                    // 数据库中查到数据了
                    List<ActionMessagePojo> actionMessagePojoList = serviceResult.getResult().getList();
                    for (ActionMessagePojo actionMessagePojo : actionMessagePojoList) {
                        String apiResultJson = JSONObject.toJSONString(actionMessagePojo, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
                        double score = DateUtils.stringToDate(actionMessagePojo.getCreateTime()).getTime();
                        serviceHelper.getRedisManager().zAdd(key, apiResultJson, score);
                    }
                    return serviceResult;
                } else {
                    // 数据库中没有查到数据
                    serviceHelper.getRedisManager().zAdd(key, RedisStorage.EMPTY_VALUE, 0);
                    return serviceResult;
                }
            } else {
                String totalKey = RedisKeyPrefixEnum.ACTION_MESSAGE_TOTAL.getCode() + "_" + id;
                // 这个用户有多条消息
                List<ActionMessagePojo> actionMessageList = serviceHelper.getModelHandler().stringSetToActionMessagePojoList(stringSet);
                Object o = serviceHelper.getRedisManager().get(totalKey);
                PageInfo<ActionMessagePojo> data = new PageInfo<>(actionMessageList);
                int total = 0;
                if(ObjectUtils.isEmpty(o)){
                    total = this.baseMapper.getTotalOfRedis(id);
                    serviceHelper.getRedisManager().set(totalKey,String.valueOf(total));
                }else {
                    total = Integer.parseInt(o.toString());
                }
                data.setTotal(total);
                return ServiceResult.ok(data, "动作消息分页数据OK");
            }
        } else {
            // 出错了
            log.warn("redis中key为【{}】的值为null", key);
            return ServiceResult.ok(new PageInfo<>(null), "动作消息分页数据OK");
        }
    }

    /**
     * @Description: 新增动作消息
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2023/1/616:04
     */
    @Override
    public ServiceResult handleActionMessage(ActionMessage actionMessage, List<String> userIds) {
        this.baseMapper.insert(actionMessage);

        if (CollectionUtils.isEmpty(userIds)) {
            throw new RuntimeException("用户列表为空");
        }

        // 消息接收人列表
        List<ActionMessageUserLink> list = new ArrayList<>();
        userIds.forEach(e -> {
            String key = RedisKeyPrefixEnum.ACTION_MESSAGE_PAGE.getCode() + "_" + e;
            serviceHelper.getRedisManager().del(key);

            String unReadTotalKey = RedisKeyPrefixEnum.ACTION_MESSAGE_UNREAD_TOTAL.getCode() + "_" + e;
            serviceHelper.getRedisManager().del(unReadTotalKey);

            ActionMessageUserLink link = new ActionMessageUserLink();
            link.setActionMessageId(actionMessage.getId().intValue());
            link.setUserId(e);
            link.setIsRead(0);
            list.add(link);
        });

        //批量新增数据
        serviceHelper.getActionMessageUserLinkMapper().insertBatchSomeColumn(list);
        return ServiceResult.ok("新增消息ok");
    }


    /**
     * @Description: 新增动作消息（ 根据用户名称）
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2023/1/616:04
     */
    @Override
    public ServiceResult handleActionMessageByUserName(ActionMessage actionMessage, List<String> userNames) {
        this.baseMapper.insert(actionMessage);

        if (CollectionUtils.isEmpty(userNames)) {
            throw new RuntimeException("用户列表为空");
        }

        // 消息接收人列表
        List<ActionMessageUserLink> list = new ArrayList<>();
        for (String e : userNames) {
            ActionMessageUserLink link = new ActionMessageUserLink();
            link.setActionMessageId(actionMessage.getId().intValue());
            link.setIsRead(0);

            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userLambdaQueryWrapper.eq(User::getUserName, e);
            userLambdaQueryWrapper.isNull(User::getFatherId);
            User user = serviceHelper.getUserMapper().selectOne(userLambdaQueryWrapper);
            // 主账号
            if (user != null) {
                // 删除key
                String key = RedisKeyPrefixEnum.ACTION_MESSAGE_PAGE.getCode() + "_" + user.getId();
                serviceHelper.getRedisManager().del(key);

                String unReadTotalKey = RedisKeyPrefixEnum.ACTION_MESSAGE_UNREAD_TOTAL.getCode() + "_" + e;
                serviceHelper.getRedisManager().del(unReadTotalKey);

                link.setUserId(user.getId());
                list.add(link);
                break;
            }else {
                // 通过公司名称查找主账号
                userLambdaQueryWrapper = new LambdaQueryWrapper<>();
                userLambdaQueryWrapper.eq(User::getUserName, e);
                User fatherUser = serviceHelper.getUserMapper().selectOne(userLambdaQueryWrapper);
                // 删除key
                String key = RedisKeyPrefixEnum.ACTION_MESSAGE_PAGE.getCode() + "_" + fatherUser.getFatherId();
                serviceHelper.getRedisManager().del(key);

                String unReadTotalKey = RedisKeyPrefixEnum.ACTION_MESSAGE_UNREAD_TOTAL.getCode() + "_" + fatherUser.getFatherId();
                serviceHelper.getRedisManager().del(unReadTotalKey);

                link.setUserId(fatherUser.getFatherId());
                list.add(link);
                break;
            }
        }
        Assert.notEmpty(list, "根据公司名称列表未查询到主账户");
        //批量新增数据
        serviceHelper.getActionMessageUserLinkMapper().insertBatchSomeColumn(list);
        return ServiceResult.ok("新增消息ok");
    }


    /**
     * @param userId
     * @Description: 全部已读
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2023/1/616:27
     */
    @Override
    public void isReadAll(String userId) {
        // 更新数据库
        LambdaQueryWrapper<ActionMessageUserLink> linkLambdaQueryWrapper = new LambdaQueryWrapper<>();
        linkLambdaQueryWrapper.eq(ActionMessageUserLink::getUserId, userId);
        ActionMessageUserLink link = new ActionMessageUserLink();
        link.setIsRead(1);
        serviceHelper.getActionMessageUserLinkMapper().update(link, linkLambdaQueryWrapper);
    }

    /**
     * @param userId
     * @Description: 全部已读
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2023/1/616:27
     */
    @Override
    public void isReadAllRedis(String userId) {
        // 更新数据库
        LambdaQueryWrapper<ActionMessageUserLink> linkLambdaQueryWrapper = new LambdaQueryWrapper<>();
        linkLambdaQueryWrapper.eq(ActionMessageUserLink::getUserId, userId);
        ActionMessageUserLink link = new ActionMessageUserLink();
        link.setIsRead(1);
        serviceHelper.getActionMessageUserLinkMapper().update(link, linkLambdaQueryWrapper);

        // 删除redis中的数据
        serviceHelper.getRedisManager().del(RedisKeyPrefixEnum.ACTION_MESSAGE_PAGE.getCode() + "_" + userId);
        serviceHelper.getRedisManager().del(RedisKeyPrefixEnum.ACTION_MESSAGE_UNREAD_TOTAL.getCode() + "_" + userId);
        serviceHelper.getRedisManager().del(RedisKeyPrefixEnum.ACTION_MESSAGE_TOTAL.getCode() + "_" + userId);
    }

    /**
     * @Description: 返回未读消息的总数
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2023/2/1417:11
     */
    @Override
    public ServiceResult<Integer> unReadTotal(String userId) {
        LambdaQueryWrapper<ActionMessageUserLink> linkLambdaQueryWrapper = new LambdaQueryWrapper<>();
        linkLambdaQueryWrapper.eq(ActionMessageUserLink::getUserId, userId);
        linkLambdaQueryWrapper.eq(ActionMessageUserLink::getIsRead, 0);

        List<ActionMessageUserLink> actionMessageUserLinks = serviceHelper.getActionMessageUserLinkMapper().selectList(linkLambdaQueryWrapper);
        return ServiceResult.ok(actionMessageUserLinks.size(), "ok");
    }

    /**
     * @Description: 从redis中，返回未读消息的总数
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2023/2/1417:11
     */
    @Override
    public ServiceResult<Integer> unReadTotalRedis(String userId) {
        String key = RedisKeyPrefixEnum.ACTION_MESSAGE_UNREAD_TOTAL.getCode() + "_" + userId;
        String unReadTotal = (String) serviceHelper.getRedisManager().get(key);

        if (null != unReadTotal) {
            if (RedisStorage.EMPTY_VALUE.equals(unReadTotal)) {
                // 这个用户没有消息（redis里没有，mysql里也没有）
                return ServiceResult.ok(null, "ok");
            } else {
                // 这个用户有消息
                Integer value = Integer.valueOf(serviceHelper.getRedisManager().get(key).toString());
                return ServiceResult.ok(value, "ok");
            }
        } else {
            // redis中没有数据，需要从数据库中取数据，然后存储到redis中
            ServiceResult<Integer> serviceResult = this.unReadTotal(userId);
            log.debug("用户【[]】的未读消息数：【{}】", userId, serviceResult.getResult());
            serviceHelper.getRedisManager().set(key, serviceResult.getResult().toString());
            return ServiceResult.ok(serviceResult.getResult(), "ok");
        }
    }

    /**
     * 将接口/api/v2/actionMessage/initPage需要的数据导入到redis
     */
    @Override
    public void initPage() {
        // 删除redis中的数据
        Boolean deleteResult = serviceHelper.getRedisManager().delRedisDataByKeyPrefix(RedisKeyPrefixEnum.ACTION_MESSAGE_PAGE.getCode() + "*");
        if (deleteResult) {
            log.info("删除[{}]开头的数据成功", RedisKeyPrefixEnum.ACTION_MESSAGE_PAGE.getCode());
        }

        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        List<User> userList = serviceHelper.getUserMapper().selectList(queryWrapper);

        if (null != userList && userList.size() > 0) {
            for (User user : userList) {
                List<ActionMessagePojo> actionMessagePojoList = this.baseMapper.pageInfo(user.getId());

                String key = RedisKeyPrefixEnum.ACTION_MESSAGE_PAGE.getCode() + "_" + user.getId();

                if (null != actionMessagePojoList && actionMessagePojoList.size() > 0) {
                    // 这个用户有消息
                    for (ActionMessagePojo actionMessagePojo : actionMessagePojoList) {
                        String apiResultJson = JSONObject.toJSONString(actionMessagePojo, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
                        double score = DateUtils.stringToDate(actionMessagePojo.getCreateTime()).getTime();

                        serviceHelper.getRedisManager().zAdd(key, apiResultJson, score);
                    }
                } else {
                    // 表示这个用户没有消息
                    serviceHelper.getRedisManager().zAdd(key, RedisStorage.EMPTY_VALUE, 0);
                }
            }
            log.info("将接口/api/v2/actionMessage/initPage需要的数据导入到redis完成");
        } else {
            log.warn("user表中的没有数据，无法将接口/api/v2/actionMessage/initPage需要的数据导入到redis");
        }
    }

    /**
     * 将接口/api/v2/actionMessage/initUnReadTotal需要的数据导入到redis
     */
    @Override
    public void initUnReadTotal() {
        // 删除redis中的数据
        Boolean deleteResult = serviceHelper.getRedisManager().delRedisDataByKeyPrefix(RedisKeyPrefixEnum.ACTION_MESSAGE_UNREAD_TOTAL.getCode() + "*");
        if (deleteResult) {
            log.info("删除[{}]开头的数据成功", RedisKeyPrefixEnum.ACTION_MESSAGE_UNREAD_TOTAL.getCode());
        }

        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        List<User> userList = serviceHelper.getUserMapper().selectList(queryWrapper);

        if (null != userList && userList.size() > 0) {
            for (User user : userList) {
                ServiceResult<Integer> serviceResult = this.unReadTotal(user.getId());

                String key = RedisKeyPrefixEnum.ACTION_MESSAGE_UNREAD_TOTAL.getCode() + "_" + user.getId();

                if (null != serviceResult && null != serviceResult.getResult() && serviceResult.getResult() > 0) {
                    // 这个用户有未读消息
                    serviceHelper.getRedisManager().set(key, serviceResult.getResult().toString());
                } else {
                    // 表示这个用户没有未读消息
                    serviceHelper.getRedisManager().set(key, "0");
                }
            }
            log.info("将接口/api/v2/actionMessage/initUnReadTotal需要的数据导入到redis完成");
        } else {
            log.warn("user表中的没有数据，无法将接口/api/v2/actionMessage/initUnReadTotal需要的数据导入到redis");
        }
    }
}